﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Acando.Dynamics.CRM.Silverlight.Library.Helper;
using Acando.Dynamics.CRM.Silverlight.Library.Controls.FieldControls;
using Acando.Dynamics.CRM.Silverlight.Library.Interfaces;
using Acando.Dynamics.CRM.Silverlight.Library.Model;
using Acando.Dynamics.CRM.Silverlight.Library.MetaSdk;
using Acando.Dynamics.CRM.Silverlight.Library.CrmSdk;
using System.Collections.ObjectModel;
using System.Windows.Data;
using Acando.Dynamics.CRM.Silverlight.Library.Converter;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;


namespace Acando.Dynamics.CRM.Silverlight.Library.Dialogs
{
    public partial class LookupDialog : UserControl
    {
        private Panel Parent { get; set; }
        private String _organame;
        private IMetaDataLayer _metadatalayer;

        public LookupDialog(LookupAttributeMetadata lookupdata, String organame, IMetaDataLayer metadatalayer)
        // public LookupDialog(LookupAttributeMetadata lookupdata, String organame, IMetaDataLayer metadatalayer, Panel parent) --> hosting Control definiert wo dialog angezeigt werden soll 
        {
            this._organame = organame;
            this._metadatalayer = metadatalayer;
            this.Parent = ApplicationContext.Current.GetParentForDialogs();
            this.LookupMeta = lookupdata;
           
            InitializeComponent();

            this.btnSeach.Click += (sender,args) => this.filterItems();
            // warum dauert das anzeigen von der LoadingBar solange????
            this.btnSeach.Click += (sender, args) => this.pnlLoading.Visibility = Visibility.Visible;
            this.cmbPossibleTypes.SelectionChanged += (sender, args) => this.txSearchBy.Text = String.Empty;
            //this.txSearchBy.TextChanged += (sender,args) => this.filterItems();
            this.findPossibleTypes();
        }

        private void filterItems()
        {
            if (!String.IsNullOrEmpty(this.txSearchBy.Text) && !String.IsNullOrEmpty(this.txSearchBy.Text.Trim()))
            {
                QueryExpression query = new QueryExpression();

                ConditionExpression condition = new ConditionExpression();
                condition.AttributeName = ((EntityMetadata)this.cmbPossibleTypes.SelectedItem).PrimaryField.ToString();
                condition.Values = new Object[] { String.Format("%{0}%", this.txSearchBy.Text) };
                condition.Operator = ConditionOperator.Like;

                ColumnSet cols = new ColumnSet();
                cols.Attributes = new String[] { ((EntityMetadata)this.cmbPossibleTypes.SelectedItem).PrimaryField.ToString() };
                query.ColumnSet = cols;
                query.Criteria = new FilterExpression();
                query.Criteria.FilterOperator = LogicalOperator.And;
                query.Criteria.Conditions = new ConditionExpression[] { condition };

                this.LoadDialogData(query);
            }
            else
            {
                QueryExpression query = new QueryExpression();

                ColumnSet cols = new ColumnSet();
                cols.Attributes = new String[] { ((EntityMetadata)this.cmbPossibleTypes.SelectedItem).PrimaryField.ToString() };
                query.ColumnSet = cols;

                this.LoadDialogData(null);
            }

            this.IsEnabled = false;
        }

        public event EventHandler<EventArgs> DialogClosed;

        #region Properties

        /// <summary>
        /// Name of the lookup attribute
        /// </summary>
        private string AttributeName
        {
            get;
            set;
        }

        private Type TargetType { get; set; }

        private LookupAttributeMetadata LookupMeta
        {
            get;
            set;
        }

        public IList<EntityMetadata> PossibleTypes
        {
            get { return (IList<EntityMetadata>)GetValue(PossibleTypesProperty); }
            set { SetValue(PossibleTypesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for PossibleTypes.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PossibleTypesProperty =
            DependencyProperty.Register("PossibleTypes", typeof(IList<EntityMetadata>), typeof(LookupDialog), null);


        public CrmReference ResultValue
        {
            get { return (CrmReference)GetValue(ResultValueProperty); }
            set { SetValue(ResultValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ResultValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ResultValueProperty =
            DependencyProperty.Register("ResultValue", typeof(CrmReference), typeof(LookupDialog), null);

        public bool DialogResult { get; set; }

        #endregion

        #region Methods


        private void findPossibleTypes()
        {
            this._metadatalayer.LoadMetaData(this.LookupMeta.EntityLogicalName, loadmetadataCallback);
            
            //MetadataCache metadataCache = new MetadataCache();
            //metadataCache.MetadataLoaded += new MetadataCache.MetadataLoadedHandler(metadataCache_MetadataLoaded);
            //metadataCache.LoadMetadata(this.LookupMeta.EntityLogicalName); 
        }

        public void ShowDialog()
        {
            if (!this.Parent.Children.Contains(this))
            {
                this.Parent.Children.Add(this);
                
                this.Visibility = Visibility.Visible;

                if (this.PossibleTypes == null)
                {
                    this.findPossibleTypes();
                }

                this.IsEnabled = true;
            }
        }

        private void loadmetadataCallback(EntityMetadata metadata)
        {
            MetaSdkLookupTypesHelper helper = new MetaSdkLookupTypesHelper();
            helper.GetPossibleLookupTypesCompleted += new MetaSdkLookupTypesHelper.GetPossibleLookupTypesHandler(helper_GetPossibleLookupTypesCompleted);
            helper.GetPossibleLookupTypes(metadata, this.LookupMeta.LogicalName, this._metadatalayer);
        }

        void helper_GetPossibleLookupTypesCompleted(List<EntityMetadata> metadataList)
        {
            this.cmbPossibleTypes.ItemsSource = metadataList;
            this.cmbPossibleTypes.DisplayMemberPath = "DisplayName.UserLocLabel.Label";
            this.PossibleTypes = metadataList;

            if (metadataList.Count > 0)
            {
                this.cmbPossibleTypes.IsEnabled = true;
                this.cmbPossibleTypes.SelectedIndex = 0;
                //this.LoadDialogData();
            }
            else
                this.IsEnabled = true;
        }

        protected void LoadDialogData(QueryExpression query)
        {
            if (cmbPossibleTypes.SelectedItem != null)
            {
                DynamicDataModel da = new DynamicDataModel(((EntityMetadata)this.cmbPossibleTypes.SelectedItem).LogicalName, this._organame);
                da.RetrieveMultipleCompleted += new EventHandler<RetrieveMultipleCompletedEventArgs>(s_RetrieveMultipleCompleted);

                if (query == null)
                    da.RetrieveMultiple();

                else
                    da.RetrieveMultiple(query);
            }
        }

        void s_RetrieveMultipleCompleted(object sender, RetrieveMultipleCompletedEventArgs e)
        {
           
            ObservableCollection<DynamicEntity> collection = CrmServiceConversions.ConvertToCollection<DynamicEntity>(e.Result);
            String primerFieldName = ((EntityMetadata)this.cmbPossibleTypes.SelectedItem).PrimaryField;

            // to lookup dialog needs to display the PrimaryField of the dynamic entity. The container is a 
            // Property of the DynamicEntity class which is used for this purpose. 
            foreach (var dynamicEntitiy in collection.Where( c=> c.Contains(primerFieldName)))
                dynamicEntitiy.Container = dynamicEntitiy[primerFieldName].ToString();
                //dynamicEntitiy.Container = dynamicEntitiy[((EntityMetadata)this.cmbPossibleTypes.SelectedItem).PrimaryField].ToString();
            
            

            

            this.listItems.ItemsSource = collection;
            this.listItems.Tag = collection.ToList();

            this.listItems.DisplayMemberPath = "Container";
            this.IsEnabled = true;

            if (collection.Count == 0)
                MessageBox.Show("No data found with the stated characteristics");
            
            this.pnlLoading.Visibility = Visibility.Collapsed;
        }

        
        private void CloseControl()
        {
            this.Parent.Children.Remove(this);
            this.Visibility = Visibility.Collapsed;
            this.DialogClosed(this, new EventArgs());
        }

        #endregion

        #region Dialog-events

        private void btnSelectFromList_Click(object sender, RoutedEventArgs e)
        {
            if (this.listItems.SelectedIndex >= 0)
            {
                CrmReference r = CreateCrmReference();

                r.name = ((this.listItems.SelectedItem as DynamicEntity)[((EntityMetadata)this.cmbPossibleTypes.SelectedItem).PrimaryField] as String);
                r.type = (this.listItems.SelectedItem as DynamicEntity).Name;
                r.Value = ((this.listItems.SelectedItem as DynamicEntity)[((EntityMetadata)this.cmbPossibleTypes.SelectedItem).PrimaryKey] as CrmSdk.Key).Value;
                this.ResultValue = r;

                this.txSearchBy.Text = String.Empty;
                this.listItems.ItemsSource = new ObservableCollection<DynamicEntity>();
                this.DialogResult = true;
                this.CloseControl();
            }
            else
                MessageBox.Show("Please select record first.");
        }

        private CrmReference CreateCrmReference()
        {
            CrmReference r;
            if (this.LookupMeta.AttributeType.Value == AttributeType.Lookup)
                r = new Lookup();
            else if (this.LookupMeta.AttributeType.Value == AttributeType.Owner)
                r = new Owner();
            else if (this.LookupMeta.AttributeType.Value == AttributeType.Customer)
                r = new Customer();
            else
                throw new NotSupportedException();
            return r;
        }



        private void btnRemoveValue_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
            this.ResultValue = this.CreateCrmReference();
            this.ResultValue.IsNull = true;
            this.ResultValue.IsNullSpecified = true;
            this.CloseControl();
        }

        private void btnCancelSelection_Click(object sender, RoutedEventArgs e)
        {
            this.txSearchBy.Text = String.Empty;
            this.listItems.ItemsSource = new ObservableCollection<DynamicEntity>();
            this.DialogResult = false;
            this.CloseControl();
        }
        #endregion



    }
}
